package com.amoyt.project.security.config;


import com.amoyt.project.config.CorsConfig;
import com.amoyt.project.security.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfigurationSource;

@Configuration
@EnableWebSecurity // 启用Web安全配置
@EnableMethodSecurity // 支持方法级别的权限控制（如 @PreAuthorize）
public class SecurityConfig {

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    // 注入 CORS 配置源（复用在 CorsConfig 中定义的配置）
    @Autowired
    private CorsConfigurationSource corsConfigurationSource;

    /**
     * 授权失败处理器 （也即无权限）
     */
    @Autowired
    private AccessDeniedHandler accessDeniedHandler;

    /**
     * 认证失败处理器 (也即未登录)
     */
    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;

    //创建BCryptPasswordEncoder注入容器
    @Bean("myEncoder")
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //2、重写WebSecurity中的authenticationManagerBean来创建一个供咱们使用的AuthenticationManager对象
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }

    //放行登录接口
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 关闭 CSRF（前后端分离场景常用）
                .csrf(csrf -> csrf.disable())
                //禁用默认表单登录页面和接口 TODO 需要自定义
                .formLogin(form -> form.disable())
                //禁用注销接口 TODO 需要自定义
                .logout(logout -> logout.disable())
                //不通过Session获取SecurityContext 前后端分离，不走session
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                // 配置请求授权规则 （核心：放行静态资源和公开接口）
                .authorizeHttpRequests(auth -> auth
                        // 关键：放行所有 OPTIONS 预检请求
                        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                        // 1. 放行 Swagger 相关资源（对应原拦截器的文档路径）
                        .requestMatchers(
                                "/doc.html",
                                "/webjars/**",
                                "/swagger-resources/**",
                                "/v3/api-docs/**",
                                "/swagger-ui/**"
                        ).permitAll() // 允许匿名访问

                        // 2. 放行公开业务接口（对应原拦截器的业务路径）
                        .requestMatchers(
                                "/admin/login",
                                "/visitor/login",
                                "/visitor/code",
                                "/visitor/register",
                                "/visitor/verify",
                                "/web/**"
//                                "/web/notice/**",
//                                "/web/file/**"
                        ).permitAll() // 允许匿名访问

                        // 3. 其他所有请求必须认证（登录后才能访问）
                        .anyRequest().authenticated()
                );


        // 允许跨域,启用CORS并关联配置源
        http.cors(cors -> cors.configurationSource(corsConfigurationSource));

        // 在 UsernamePasswordAuthenticationFilter 之前添加 JWT 过滤器
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        /*在 JWT前面添加 RefreshTokenFilter token刷新过滤器，比如登录用户刷新首页这种（没必要，这是jwt诶）
        http.addFilterBefore(refreshTokenFilter, JwtAuthenticationTokenFilter.class);*/

        // 配置异常处理器
        http.exceptionHandling(ex -> ex
                .authenticationEntryPoint(authenticationEntryPoint) // 认证失败处理器
                .accessDeniedHandler(accessDeniedHandler) // 授权失败处理器
        );

        return http.build();
    }
}